
#include <BRender>
#include <BOpenGL>
#include "IPixmap.h"
#include "member_BWidget.h"
#include "member_BTexture.h"

using namespace BWE;

IPixmap::IPixmap()
{
	_fbo = 0;
	_rbo_depth = 0;
	_rbo_stencil = 0;
	_size.set(100, 100);
	_dirty = true;
}
IPixmap::~IPixmap()
{

}

void IPixmap::setSize(const BSize& size)
{
	if (_size != size)
	{
		_size = size;
		_dirty = true;
	}
}
const BSize& IPixmap::size() const
{
	return _size;
}

bool IPixmap::update()
{
	int width = _size.width();
	int height = _size.height();
	if (width < 1 || height < 1)
		return false;

	BTexture::bind();

	GLuint tbo = texture_member(this)->tbo;

	if (tbo == 0)
		return false;

	//if (_fbo == 0)
	//{
	//	GLint backup_frame_buffer;
	//	glGetIntegerv(GL_FRAMEBUFFER_BINDING, &backup_frame_buffer);
	//
	//	glGenFramebuffers(1, &_fbo);
	//	if (!_fbo)
	//		return false;
	//
	//	glBindFramebuffer(GL_FRAMEBUFFER, _fbo);
	//	{
	//		glGenRenderbuffers(1, &_rbo_depth);
	//		glBindRenderbuffer(GL_RENDERBUFFER, _rbo_depth);
	//		glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
	//		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _rbo_depth);
	//
	//		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
	//		glBindTexture(GL_TEXTURE_2D, tbo);
	//		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
	//		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
	//		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	//		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	//		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, 0);
	//		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tbo, 0);
	//	}
	//	glBindFramebuffer(GL_FRAMEBUFFER, backup_frame_buffer);
	//}

	if (_dirty)
	{
		int width = _size.width();
		int height = _size.height();

		if (!_fbo)
		{
			glGenFramebuffers(1, &_fbo);
			glGenRenderbuffers(1, &_rbo_depth);
		}
		if (_fbo)
		{
			glBindFramebuffer(GL_FRAMEBUFFER, _fbo);
			glBindRenderbuffer(GL_RENDERBUFFER, _rbo_depth);
			glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _rbo_depth);
		}
		if (!tbo)
		{
			glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
			glGenTextures(1, &tbo);
		}
		if (tbo)
		{
			glBindTexture(GL_TEXTURE_2D, tbo);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, 0);
			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tbo, 0);
		}
		_dirty = false;
	}

	if (_rbo_depth == 0)
		return false;

	return true;
}

bool IPixmap::bind() const
{
	GLuint tbo = texture_member(this)->tbo;
	if (tbo)
	{
		glBindTexture(GL_TEXTURE_2D, tbo);
		return true;
	}
	glBindTexture(GL_TEXTURE_2D, 0);
	return false;
}
